package com.mallcai.bigdata.ladon.tools;

/**
 * @author gst
 * @date 2019-12-30 14:53
 */
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;

public final class OssUtil {

    private static void checkOssInfo(OssInfo ossInfo) {
        if (ossInfo == null) {
            throw new RuntimeException("传入对象为空");
        } else if (StringUtils.isBlank(ossInfo.getAccessKeyId())) {
            throw new RuntimeException("accessKeyId不能为空!");
        } else if (StringUtils.isBlank(ossInfo.getAccessKeySecret())) {
            throw new RuntimeException("accessKeySecret不能为空!");
        } else if (StringUtils.isBlank(ossInfo.getEndpoint())) {
            throw new RuntimeException("endpoint不能为空!");
        } else if (StringUtils.isBlank(ossInfo.getBucketName())) {
            throw new RuntimeException("bucketName不能为空!");
        } else if (StringUtils.isBlank(ossInfo.getRootObject())) {
            throw new RuntimeException("根目录不能为空!");
        } else {
            String filePath = StringUtils.trim(ossInfo.getRootObject());
            if (!StringUtils.endsWith(filePath, "/")) {
                ossInfo.setRootObject(filePath + "/");
            }

        }
    }


    /**
     * 上传文件至OSS,采用默认配置
     *
     * @param fileName 保存至OSS后的文件名称
     * @param is       文件输入流(文件来源)
     * @return 下载路径
     * @throws Exception
     */
    public static String defaultUpload(String fileName, InputStream is) throws Exception {
        //TODO 修改为可用的地址
        OssInfo ossInfo = new OssInfo();
        ossInfo.setDownloadUrl("https://XXXX.aliyuncs.com/");
        ossInfo.setAccessKeyId("XXXXX");
        ossInfo.setAccessKeySecret("XXXXX");
        ossInfo.setBucketName("XXXXX");
        ossInfo.setEndpoint("https://XXXXX.aliyuncs.com");
        ossInfo.setRootObject("ladon");
        checkOssInfo(ossInfo);
        OSSClient ossClient = new OSSClient(ossInfo.getEndpoint(), ossInfo.getAccessKeyId(), ossInfo.getAccessKeySecret());
        String filePath = ossInfo.getRootObject() + fileName;

        try {
            ossClient.putObject(ossInfo.getBucketName(), filePath, is);
            return ossInfo.getDownloadUrl() + filePath;
        } catch (Exception e) {
            throw new RuntimeException("上传文件失败" + e.getMessage(), e.getCause());
        } finally {
            ossClient.shutdown();
        }

    }

    /**
     * 上传文件至OSS
     *
     * @param ossInfo  OSS配置信息
     * @param fileName 保存至OSS后的文件名称
     * @param is       文件输入流(文件来源)
     * @throws Exception
     */
    public static void uploadStream(OssInfo ossInfo, String fileName, InputStream is) throws Exception {
        checkOssInfo(ossInfo);
        OSSClient ossClient = new OSSClient(ossInfo.getEndpoint(), ossInfo.getAccessKeyId(), ossInfo.getAccessKeySecret());
        String filePath = ossInfo.getRootObject() + fileName;

        try {
            ossClient.putObject(ossInfo.getBucketName(), filePath, is);
        } catch (Exception e) {
            throw new RuntimeException("上传文件失败" + e.getMessage(), e.getCause());
        } finally {
            ossClient.shutdown();
        }

    }


    /**
     * 在OSS上创建文件夹
     *
     * @param ossInfo OSS配置信息
     * @param dirName 文件夹名称
     * @throws Exception
     */
    public static void createDir(OssInfo ossInfo, String dirName) throws Exception {
        checkOssInfo(ossInfo);
        dirName = StringUtils.trim(dirName);
        if (StringUtils.isBlank(dirName)) {
            throw new RuntimeException("文件夹名称不能为空!");
        } else {
            if (!StringUtils.endsWith(dirName, "/")) {
                dirName = dirName + "/";
            }

            OSSClient ossClient = new OSSClient(ossInfo.getEndpoint(), ossInfo.getAccessKeyId(), ossInfo.getAccessKeySecret());

            try {
                ossClient.putObject(ossInfo.getBucketName(), dirName, new ByteArrayInputStream(new byte[0]));
            } catch (Exception e) {
                throw new RuntimeException("创建文件夹失败", e.getCause());
            } finally {
                ossClient.shutdown();
            }

        }
    }

    /**
     * 上传大文件流
     *
     * @param ossInfo       OSS配置信息
     * @param localFileName 本地文件路径
     * @param fileName      文件名称
     * @throws Exception
     */
    public static void uploadBigStream(OssInfo ossInfo, String localFileName, String fileName) throws Exception {
        checkOssInfo(ossInfo);
        OSSClient ossClient = new OSSClient(ossInfo.getEndpoint(), ossInfo.getAccessKeyId(), ossInfo.getAccessKeySecret());
        String filePath = ossInfo.getRootObject() + fileName;
        UploadFileRequest uploadFileRequest = new UploadFileRequest(ossInfo.getBucketName(), filePath);
        uploadFileRequest.setUploadFile(localFileName);
        uploadFileRequest.setTaskNum(5);
        uploadFileRequest.setPartSize(1048576L);
        uploadFileRequest.setEnableCheckpoint(true);

        try {
            ossClient.uploadFile(uploadFileRequest);
        } catch (Throwable e) {
            throw new RuntimeException("断点上传文件失败", e);
        } finally {
            ossClient.shutdown();
        }

    }

    /**
     * 检查文件是否在OSS上存在
     *
     * @param ossInfo    OSS配置信息
     * @param objectName 文件名称
     * @return
     * @throws Exception
     */
    public static boolean checkObjectExist(OssInfo ossInfo, String objectName) throws Exception {
        checkOssInfo(ossInfo);
        String key = ossInfo.getRootObject() + objectName;
        OSSClient ossClient = new OSSClient(ossInfo.getEndpoint(), ossInfo.getAccessKeyId(), ossInfo.getAccessKeySecret());
        boolean found = false;

        try {
            found = ossClient.doesObjectExist(ossInfo.getBucketName(), key);
        } catch (Exception e) {
            throw new RuntimeException("判断文件是否存在失败", e.getCause());
        } finally {
            ossClient.shutdown();
        }

        return found;
    }

    /**
     * 删除OSS上指定的文件
     *
     * @param ossInfo  OOS配置信息
     * @param fileName 文件名称
     * @throws Exception
     */
    public static void deleteFile(OssInfo ossInfo, String fileName) throws Exception {
        checkOssInfo(ossInfo);
        String key = ossInfo.getRootObject() + fileName;
        OSSClient ossClient = new OSSClient(ossInfo.getEndpoint(), ossInfo.getAccessKeyId(), ossInfo.getAccessKeySecret());

        try {
            ossClient.deleteObject(ossInfo.getBucketName(), key);
        } catch (Exception e) {
            throw new RuntimeException("删除文件失败", e.getCause());
        } finally {
            ossClient.shutdown();
        }

    }

    /**
     * 批量删除OSS上的文件
     *
     * @param ossInfo   OSS配置信息
     * @param fileNames 文件列表
     * @return 已删除的文件列表
     * @throws Exception
     */
    public static List<String> deleteFiles(OssInfo ossInfo, List<String> fileNames) throws Exception {
        if (fileNames != null && !fileNames.isEmpty()) {
            checkOssInfo(ossInfo);
            ArrayList keys = new ArrayList();
            fileNames.forEach((v) -> {
                keys.add(ossInfo.getRootObject() + v);
            });
            OSSClient ossClient = new OSSClient(ossInfo.getEndpoint(), ossInfo.getAccessKeyId(), ossInfo.getAccessKeySecret());
            DeleteObjectsRequest delReq = new DeleteObjectsRequest(ossInfo.getBucketName());
            delReq.setQuiet(false);
            delReq.setKeys(keys);
            new ArrayList();

            List deletedObjects;
            try {
                DeleteObjectsResult oe = ossClient.deleteObjects(delReq);
                deletedObjects = oe.getDeletedObjects();
            } catch (Exception e) {
                throw new RuntimeException("删除文件列表失败", e.getCause());
            } finally {
                ossClient.shutdown();
            }

            return deletedObjects;
        } else {
            return new ArrayList();
        }
    }

    /**
     * @param ossInfo  OSS配置信息
     * @param fileName 文件名称
     * @return Access Control List
     * @throws Exception
     */
    public static ObjectAcl getObjectAcl(OssInfo ossInfo, String fileName) throws Exception {
        checkOssInfo(ossInfo);
        String filePath = ossInfo.getRootObject() + fileName;
        OSSClient ossClient = new OSSClient(ossInfo.getEndpoint(), ossInfo.getAccessKeyId(), ossInfo.getAccessKeySecret());
        ObjectAcl objectAcl = null;

        try {
            objectAcl = ossClient.getObjectAcl(ossInfo.getBucketName(), filePath);
        } catch (Exception e) {
            throw new RuntimeException("获取文件ACL失败", e.getCause());
        } finally {
            ossClient.shutdown();
        }

        return objectAcl;
    }

    /**
     * 获取指定文件夹下的文件列表
     *
     * @param ossInfo OSS配置信息
     * @param dir     文件夹名称
     * @param maxSize 最大返回数量
     * @return 文件列表
     */
    public static List<String> getListFiles(OssInfo ossInfo, String dir, int maxSize) {
        checkOssInfo(ossInfo);
        boolean maxKeys = true;
        String nextMarker = null;
        OSSClient ossClient = new OSSClient(ossInfo.getEndpoint(), ossInfo.getAccessKeyId(), ossInfo.getAccessKeySecret());
        ArrayList names = new ArrayList();
        byte total = 0;

        try {
            ObjectListing objectListing;
            List<OSSObjectSummary> objs;
            try {
                do {
                    ListObjectsRequest oe = new ListObjectsRequest(ossInfo.getBucketName());
                    oe.setMarker(nextMarker);
                    oe.setMaxKeys(Integer.valueOf(200));
                    String prefix = ossInfo.getRootObject();
                    if (StringUtils.isNotBlank(dir)) {
                        prefix = prefix + StringUtils.trim(dir);
                    }

                    oe.setPrefix(prefix);
                    objectListing = ossClient.listObjects(oe);
                    int size = objectListing.getObjectSummaries().size();
                    nextMarker = objectListing.getNextMarker();
                    if (total + size < maxSize) {
                        objs = objectListing.getObjectSummaries();
                    } else {
                        objs = objectListing.getObjectSummaries().subList(0, maxSize - total);
                    }

                    objs.forEach((v) -> {
                        names.add(v.getKey());
                    });
                } while (objs.size() >= 200 && objectListing.isTruncated());
            } catch (Exception e) {
                throw new RuntimeException("获取文件列表失败", e.getCause());
            }
        } finally {
            ossClient.shutdown();
        }

        return names;
    }
}

